#coding=utf-8
from django.shortcuts import render,render_to_response
from django.http import HttpResponseRedirect,HttpResponse
from django.template import RequestContext
from math import log
import MySQLdb
import string,StringIO
import csv
import numpy as np
#import pandas as pd
import json
import random
import os
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
import operator
import mlpy
import hashlib




def sql_select(text):
    conn=MySQLdb.connect(host='139.129.250.57',user="root",passwd="Piclass520",db="sjfx",port=3306,charset='utf8')
    cur = conn.cursor()
    cur.execute(text)
    res=cur.fetchall()
    cur.close()
    conn.commit()
    conn.close()
    return res

def sql_write(text):
    conn=MySQLdb.connect(host='139.129.250.57',user="root",passwd="Piclass520",db="sjfx",port=3306,charset='utf8')
    cur = conn.cursor()
    cur.execute(text)
    cur.close()
    conn.commit()
    conn.close()

def get_md5(password):
    password = password + 'sjfx'
    md5 = hashlib.md5()
    md5.update(password.encode('utf-8'))
    return md5.hexdigest()

def distance(x,y):    #欧式距离计算函数
    result = flag = 0
    for i in range(len(x)):     # i维的距离计算
        flag = (x[i]-float(y[i]))**2   
        result += flag
    return result**0.5   # float型

def distance2(x,y):          #计算两点的距离 重心法
    result = flag = 0
    for i in range(len(x)):
        flag = (x[i]-y[i])**2
        result = result + flag
    return round(result**0.5,2)


def knn_model(train_set,test_set,k):   # KNN算法（训练集最后一列为类别； 第一行为表头）
    min_distance = distance(test_set,train_set[1])  # 第0行为表头,跳过 
    shuxing = train_set[0][:-1] # 保存所有属性值（最后一列为类别，不保存）
    all_labels = [train_set[1][-1]]  # 保存所有不同的类别       
    label = train_set[1][-1]
    temp_dis = [min_distance]      # 用于距离排序的列表
    temp_label = {min_distance:label}  # 保存距离相应的label(字典)
    for t in train_set[2:]:
        dis = distance(test_set,t)
        temp_dis.append(dis)
        temp_label[dis] = t[-1]
        if all_labels.count(t[-1]) == 0:  # 如果该类别没有出现，则添加进去
            all_labels.append(t[-1]) 
    temp_dis.sort()      # 距离升序的列表
    label = [temp_label[temp_dis[0]]]  # k个距离最近对象所对应的标签(列表)
    for i in range(1,k):
        label.append(temp_label[temp_dis[i]]) 
    flag_label = label[0]      # falg保存最终类别
    for i in range(k):
        if flag_label < label.count(label[i]):
            flag_label = label[i]
    return flag_label,all_labels,shuxing


def lagrange_model(testset_y,testset_x,n,value_x,k):    # 拉格朗日插值函数
    '''
    testset_y(x):纵(横)坐标组成的向量；n:被插值的位置；value_x:缺失值的横坐标；k:取前后数据的个数
    '''
    x = list(testset_x[n-k:n]) + list(testset_x[n+1:n+1+k])
    y = list(testset_y[n-k:n]) + list(testset_y[n+1:n+1+k])   
    x1 = []
    y1 = []
    for i in range(len(y)):    # 剔除所选范围内的空值
        if y[i] != '':
             y1.append(y[i])
             x1.append(x[i])
    result = 0.0      # 保存插值结果
    for i in range(len(y1)):
        t = y1[i]
        for j in range(len(y1)):
            if i != j:
                t *= (float(value_x)-x1[i])/(x1[j]-x1[i])     # float(a) !不可为int
        result += t 
    return result

def data_isnull(testset_x,testset_y,k):   # 判断是否需要插值
    res = []
    for i in range(len(testset_y)):   # j为行
        if testset_y[i] == '':
            res.append([testset_x[i],lagrange_model(testset_y,testset_x,i,testset_x[i],k)])    # 被插值的列/缺失值的位置
    return res


def random_k(data,k):    # 随机选取初始的类中心(k-means)
    center=[]
    a=0
    if k>=len(data):
        return 0   # k超出范围
    c=len(data)/k
    for a in range(k):
       center.append(a*c+random.randint(0,c-1)+1)
    return center    # 初始聚类的中心组号列表


def centrel_data(data,record,):     # 求类的中心(k-means)
    centrel=[]
    for x in range(len(data[0])):
        centrel.append(0)
        for a in record:
            centrel[x]+= data[a][x]
        centrel[x]/=len(record)
    return  centrel
    

def kmeans_model(data,k,b):
    record=[]
    if k==len(data):
        for i in range(len(data)):
            record.append([i])
        return record
        
    x=0         # x 为循环总次数
    j=0
    centrel=[[]]
    for i in b:         #创建初始类的中心
        centrel[x].append(data[i])
    for x in range(len(data)):        
        record.append([])
        for j in range(k):
            record[x].append([])        
        for i in range(len(data)):          #将各组数据归类
            y=0
            dis0=distance(data[i],centrel[x][y])
            for j in range(k):              #寻找最近的类中心
                dis=distance(data[i],centrel[x][j])
                if dis<dis0:
                    dis0=dis
                    y=j
            record[x][y].append(i)          #将组号添加到类中
        centrel.append([])
        suc=0
        for y in range(k):         #计算类的中心
            centrel[x+1].append(centrel_data(data,record[x][y]))
            if abs(cmp(centrel[x+1][y],centrel[x][y]))!=0:      #检查中心是否有变化
                suc=1
        if suc==0:
            return record
            break


def pca_model(X,k):    # 二维训练集/降到k维
    X = np.array(X)
    n_samples, n_features = X.shape
    mean = np.array([np.mean(X[:,i]) for i in range(n_features)])  # 求平均值
    norm_X = X - mean   #一般化
    scatter_matrix = np.dot(np.transpose(norm_X),norm_X)  #做散射矩阵
    eig_val, eig_vec = np.linalg.eig(scatter_matrix)   #计算特征值和特征向量
    eig_pairs = [(np.abs(eig_val[i]), eig_vec[:,i]) for i in range(n_features)]
    eig_pairs.sort(reverse=True)  # 从大到小的选择K个特征值对应的特征向量
    feature = np.array([ele[1] for ele in eig_pairs[:k]])   # 选择最大的特征向量
    result = np.dot(norm_X,np.transpose(feature))  #转化得到降维以后的新的数据
    return result

#X = np.array([[-1, 1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])  #给出二维的数据训练集 
#print pca(X,1)


#构造决策树，采用Python字典来递归构造
def treeGrowth(dataSet,features):  
    classList = [example[-1] for example in dataSet]  
    if classList.count(classList[0])==len(classList):  
        return classList[0]  
    if len(dataSet[0])==1:  
        return classify(classList)  
  
    bestFeat = findBestSplit(dataSet) 
    bestFeatLabel = features[bestFeat]  
    myTree = {bestFeatLabel:{}}  
    featValues = [example[bestFeat] for example in dataSet]  
    uniqueFeatValues = set(featValues)  
    del (features[bestFeat])  
    for values in uniqueFeatValues:  
        subDataSet = splitDataSet(dataSet,bestFeat,values)  
        myTree[bestFeatLabel][values] = treeGrowth(subDataSet,features)  
    return myTree 

#当没有多余的feature，但是剩下的样本不完全是一样的类别是，采用出现次数多的那个类别
def classify(classList):  
    ''''' 
    find the most in the set 
    '''  
    classCount = {}  
    for vote in classList:  
        if vote not in classCount.keys():  
            classCount[vote] = 0  
        classCount[vote] += 1  
    sortedClassCount = sorted(classCount.iteritems(),key = operator.itemgetter(1),reverse = True)  
    return sortedClassCount[0][0]  
 
#寻找用于分裂的最佳属性：（遍历所有属性，算信息增益）
def findBestSplit(dataset):  
    numFeatures = len(dataset[0])-1  
    baseEntropy = calcShannonEnt(dataset)  
    bestInfoGain = 0.0  
    bestFeat = -1  
    for i in range(numFeatures):  
        featValues = [example[i] for example in dataset]  
        uniqueFeatValues = set(featValues)  
        newEntropy = 0.0  
        for val in uniqueFeatValues:  
            subDataSet = splitDataSet(dataset,i,val)  
            prob = len(subDataSet)/float(len(dataset))  
            newEntropy += prob*calcShannonEnt(subDataSet)  
        if(baseEntropy - newEntropy)>bestInfoGain:  
            bestInfoGain = baseEntropy - newEntropy  
            bestFeat = i  
    return bestFeat 
    
#选择完分裂属性后，就行数据集的分裂
def splitDataSet(dataset,feat,values):  
    retDataSet = []  
    for featVec in dataset:  
        if featVec[feat] == values:  
            reducedFeatVec = featVec[:feat]  
            reducedFeatVec.extend(featVec[feat+1:])  
            retDataSet.append(reducedFeatVec)  
    return retDataSet 

#计算数据集的熵
def calcShannonEnt(dataset):  
    numEntries = len(dataset)  
    labelCounts = {}  
    for featVec in dataset:  
        currentLabel = featVec[-1]  
        if currentLabel not in labelCounts.keys():  
            labelCounts[currentLabel] = 0  
        labelCounts[currentLabel] += 1  
    shannonEnt = 0.0  
  
    for key in labelCounts:  
        prob = float(labelCounts[key])/numEntries  
        if prob != 0:  
            shannonEnt -= prob*log(prob,2)  
    return shannonEnt  

#下面根据上面构造的决策树进行数据的分类
def ID3_predict(tree,newObject):  
    while isinstance(tree,dict):  
        key = tree.keys()[0]  
        tree = tree[key][newObject[key]]  
    return tree  
#决策树完


def evaluate_yy(data,aver_y):
    yy=0
    for i in range(len(data)):
        yy+=(data[i][1]-aver_y)**2
    return yy

def evaluate_xx(data,aver_x):
    xx=0
    for i in range(len(data)):
        xx+=(data[i][0]-aver_x)**2
    return xx

def evaluate_xy(data,aver_x,aver_y):
    xy=0
    for i in range(len(data)):
        xy+=(data[i][1]-aver_y)*(data[i][0]-aver_x)
    return xy

def average_(data,a):
    aver=0
    for i in range(len(data)):
        aver+=data[i][a]
    return aver/(len(data)+1)
#回归分析完

def initial_dist(data):         #计算每个点之间的距离，形成二维列表
    dist_data=[ ]
    for i in range(len(data)):
        dist_data.append([ ])
        for j in range(len(data)):
            dist = distance2(data[i],data[j])
            dist_data[i].append(dist)
    return dist_data

def find(dist,max_dist):            #传入距离表和最大距离，寻找当前最小距离 转出最小距离和对应组号
    min_dist=max_dist
    for i in range(len(dist)):
        for j in range(i+1,len(dist)):
            if dist[i][j]>=0:
                min_dist=min(min_dist,dist[i][j])
                if min_dist==dist[i][j]:
                    record=[min_dist,i,j]
    return record
            
def combine(data,a,b):          #将距离表中 两组合并 一组变为最小距离 另一组变为 负数
    for i in range(0,len(data)):
        data[i][a]=min(data[i][a],data[i][b])
        data[i][b]=-1
    for i in range(0,len(data)):
        data[a][i]=min(data[a][i],data[b][i])
        data[b][i]=-1
    data[b][b]=0
    return data

def record_data(record,a):      #记录每次变动的组和最小距离
   
    record[0]=a                 #首次传入处理
    if len(record)==1:
        record.append([a[1],a[2]])
        return record

    x=y=0

    for j in range(1,len(record)):  #判断操作类型
        if a[1] in record[j]:
            x = j
        if a[2] in record[j]:
            y = j
    if x!=0 and y!=0:
        record[x].extend(record[y])
        del record[y]
    elif y!=0 and x==0:
        record[y].append(a[1])
    elif x!=0 and y==0:
        record[x].append(a[2])
    elif x==0 and y==0:
        record.append([a[1],a[2]])
    return record
        

def main(data):
    dist=initial_dist(data)     #产生距离表
    max_dist=0

    for i in range(len(dist)):      #寻找距离表中最大值
        for j in range(i+1,len(dist)-1):
            max_dist=max(max_dist,dist[i][j])

    record=[[]]         #定义两个变量类型
    record_o=[[]]

    for i in range(len(data)-1):
        a=find(dist,max_dist)
        dist=combine(dist,a[1],a[2])
        record_o=record_data(record_o,a)
        for j in range(len(record_o)):
            record[i].append(record_o[j][:])
        record.append([])
    record.pop()
    return record
#系统聚类完

def get_median(data):  # 求list中位数
    data.sort()
    half = len(data) // 2
    return (data[half] + data[~half]) / 2



def login(request):  # 登录
    if request.method == 'GET':
        try:
            request.session['username']='anonymous'
        except:
            pass
        return render(request,'login.html')
    if request.method == 'POST':
        i = request.POST
        if i.has_key('login'):
            username = i['username'].replace(u' ',u'')
            password = i['password'].replace(u' ',u'')
            res = sql_select("SELECT * from user where username ='%s' and password='%s'"%(username,get_md5(password)))

            if len(res) != 0:        # 验证用户名、密码
                request.session['username'] = res[0][2]
                return render(request,"index.html",{'user':username})
            else:
                return render_to_response("login.html",{'i':len(res)},context_instance=RequestContext(request))  # 登录失败
        elif i.has_key('signup'):   # 注册
            return HttpResponseRedirect('/signup.html')
        else:  # 忘记密码
            return HttpResponseRedirect('#')


def signup(request):  # 注册
    if request.method == 'GET':
        return render(request,'signup.html')   
    if request.method == 'POST':
        i = request.POST
        if i.has_key('confirm'):   # 确认注册按钮
            name = i['new_user'].replace(u' ',u'')
            pwd1 = i['pwd1'].replace(u' ',u'')
            pwd2 = i['pwd2'].replace(u' ',u'')
            email = i['new_email'].replace(u' ',u'')
            res = sql_select("SELECT * from user where username ='%s'"%(name))

            if len(res) == 0:   # 用户名不重复
                if pwd1 == pwd2:  # 两次密码一致
                    sql_write("INSERT INTO user(username,password,email) VALUES('%s','%s','%s');"%(name,get_md5(pwd1),email))
                    return HttpResponseRedirect('/succeed_signup.html')  # 注册成功
                else:
                    return render(request,"signup.html",{'i':1,'name':name,'pwd1':pwd1,'pwd2':pwd2,'email':email},context_instance=RequestContext(request))  # 密码不一致   这两种情况还需保留表单原有内容，未完成
            else:
                return render(request,"signup.html",{'res':len(res),'name':name,'pwd1':pwd1,'pwd2':pwd2,'email':email},context_instance=RequestContext(request))  # 用户已存在



def succeed_signup(request):
    if request.method == "GET":
        return render(request,'succeed_signup.html')
    if request.method == "POST":
        i = request.POST
        if i.has_key('back'):  
            return HttpResponseRedirect('/')

def index(request):                # 主页         
    if request.method == "GET":
        return render_to_response("index.html",{'user':request.session['username']})    
    if request.method == "POST":
        pass

def analysis(request):  # 数据分析
    if request.method == "GET":
        return render(request,"analysis.html",{'user':request.session['username']})

def recommend(request):  # 智能推荐
    if request.method == "GET":
        return render(request,"recommend.html",{'user':request.session['username']})

def help(request):   # 帮助中心
    if request.method == "GET":
        return render_to_response("help.html",{'user':request.session['username']})


def explore(request):
    if request.method == "GET":
        return render(request,"explore.html",{'user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        plt.rcParams['axes.unicode_minus'] = False
        plt.rcParams['font.sans-serif']=['SimHei']
        if i.has_key('submit'):   # 开始画图
            files = os.listdir('../static/tmpimage')   # 删除已有文件
            if files:
                for file in files:
                    os.remove('../static/tmpimage/' + file)

            try:
                if i['x'] != '':    # 输入数据        
                    title = i['title']
                    x = (i['x']).split(",")
                    x = map(float,x)
                    y = (i['y']).split(",")
                    y = map(float,y)
                else:    # 上传文件
                    csv_file = request.FILES["csv"].read()
                    fobj = StringIO.StringIO(csv_file) # 获取上传的文件 
                    csv_result = list(csv.reader(fobj))
                    train_set = csv_result[1:]
                    title = i['title']
                    x = []
                    y = []
                    for j in train_set:   # 跳过表头
                        x.append(float(j[0]))
                        y.append(float(j[1]))


                jc = max(y) - min(y)   # 极差
                mean_y = (np.array(y)).mean()   # 均值
                center_y = get_median(y)  # 中位数
                std_y = np.std(y)   # 标准差
                var = std_y / mean_y * 100   # 变异系数

                plt.figure(figsize=(8,4))
                plt.title(title)
                plt.xlabel("x")
                plt.ylabel("y")

                if i['type'] == 'zjzb':  # 直角坐标系
                    plt.plot(x,y,label="$y=f(x)$",color="red",linewidth=2)
                    plt.legend()
                    plt.savefig('../static/tmpimage/tmp.png')
                    plt.close()
                elif i['type'] == 'logx':  # x取对数
                    plt.semilogx(x,y,label="$y=f(x)$",color="red",linewidth=2)
                    plt.legend()
                    plt.savefig('../static/tmpimage/tmp.png')
                    plt.close()
                elif i['type'] == 'logy':  # y取对数
                    plt.semilogy(x,y,label="$y=f(x)$",color="red",linewidth=2)
                    plt.legend()
                    plt.savefig('../static/tmpimage/tmp.png')
                    plt.close()
                elif i['type'] == 'loglog':  #  x、y取对数
                    plt.loglog(x,y,label="$y=f(x)$",color="red",linewidth=2)
                    plt.legend()
                    plt.savefig('../static/tmpimage/tmp.png')
                    plt.close()
                else:    # 散点图
                    plt.scatter(x,y,color="blue",s=4)
                    plt.legend()
                    plt.savefig('../static/tmpimage/tmp.png')
                    plt.close()
                return render(request,'explore.html',{'src':'tmp.png',
                                                    'x':x,
                                                    'y':y,
                                                    'title':title,
                                                    'jc':jc,
                                                    'mean_y':mean_y,
                                                    'center_y':center_y,
                                                    'std_y':std_y,
                                                    'var':var,
                                                    'user':request.session['username']},
                                                    context_instance=RequestContext(request))
            except:
                return render(request,'404.html')



def data_iswrong(request):  # 异常值检测
    if request.method == "GET":
        return render(request,"data_iswrong.html",{'src':'','user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        if i.has_key('ok'):  # submite
            files = os.listdir('../static/tmpimage')   # 删除已有文件
            if files:
                for file in files:
                    os.remove('../static/tmpimage/' + file) 

            try:
                csv_file = request.FILES["csv"].read()
                fobj = StringIO.StringIO(csv_file) 
                csv_result = list(csv.reader(fobj))
                train_set = csv_result
                number = int(request.POST['number'])  # 第number列
                name = train_set[0][number-1]
                train_set = train_set[1:]
                data = []
                for j in range(len(train_set)):
                    data.append(train_set[j][number-1])

                data = map(float,data)

                plt.rcParams['axes.unicode_minus'] = False
                plt.rcParams['font.sans-serif']=['SimHei']
                plt.figure(figsize=(8,5))
                plt.boxplot(data)
                plt.legend()
                plt.savefig('../static/tmpimage/tmp.png')
                plt.close()

                return render(request,'data_iswrong.html',{'src':'tmp.png',
                                                        'number':number,
                                                        'user':request.session['username'],
                                                    },
                                                    context_instance=RequestContext(request))
            except:
                return render(request,'404.html')

def knn(request):
    if request.method == "GET":
        return render(request,"knn.html",{'result':'','user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        if i.has_key('ok'):
            try:  
                csv_file = request.FILES["csv"].read()
                fobj = StringIO.StringIO(csv_file) # 获取上传的文件 
                csv_result = list(csv.reader(fobj))
                train_set = csv_result  # 训练集（或为用户要分析的文件）
                test_set = (i['testset_input']).split(",")
                test_set = map(float,test_set)
                k = int(request.POST['value_k'])

                label,all_labels,shuxing = knn_model(train_set,test_set,k)


                all_labels.append('待测对象')
                len_labels = len(all_labels) - 1
                train_set2 = []       # 保存数字部分
                per_label = []    # 每一项对应的类别
                for i in train_set[1:]:
                    per_label.append(i[-1])  
                    train_set2.append(map(float,i[:-1]))# 除去类别，只保留数字

                if len(shuxing) > 2:  #采用雷达图
                    all_labels = json.dumps(all_labels,ensure_ascii=False)

                    data = []   # 传给echarts
                    for i in range(len(train_set2)):
                        data.append({'value':train_set2[i],'name':per_label[i]})
                    data.append({'value':test_set,'name':'待测对象'})
                    data = json.dumps(data,ensure_ascii=False)  

                    indicator= []  # 传给echarts
                    numb = np.array(train_set2)
                    numb = numb.transpose()
                    for i in range(len(shuxing)):
                        indicator.append({'text' :shuxing[i],'max' :max(numb[i])})
                    indicator = json.dumps(indicator,ensure_ascii=False)  
                    return render(request,"knn.html",{'length':len(shuxing),
                                                'k':k,
                                                'test_set':test_set,
                                                'label':label,
                                                'indicator':indicator,
                                                'all_labels':all_labels,
                                                'len_labels':len_labels,
                                                'data':data,
                                                'user':request.session['username']},
                                                context_instance=RequestContext(request))

                elif len(shuxing) == 2:  # 散点图
                    data = []
                    series = []
                    for i in range(len(all_labels) - 1):  # 所有不同类
                        for j in range(len(per_label)):  # 每个item对应的类
                            if per_label[j] == all_labels[i]:    # 找出同类的item，存为一组
                                series.append(train_set2[j])
                        data.append({'name':all_labels[i],'type':'scatter','data':series,'symbolSize':10})
                        series = []

                    data.append({'name':'待测对象','type':'scatter','data':[test_set],'symbolSize':10}) #
                    data = json.dumps(data,ensure_ascii=False)
                    all_labels = json.dumps(all_labels,ensure_ascii=False)
                    return render(request,"knn.html",{'length':len(shuxing),
                                                'k':k,
                                                'test_set':test_set,
                                                'label':label,
                                                'shuxing0':json.dumps(shuxing[0],ensure_ascii=False),
                                                'shuxing1':json.dumps(shuxing[1],ensure_ascii=False),
                                                'all_labels':all_labels,
                                                'len_all':len(all_labels),
                                                'len_labels':len_labels,
                                                'data':data,
                                                'user':request.session['username']},
                                                context_instance=RequestContext(request))
            except:
                return render(request,'404.html')


def lagrange(request):    
    if request.method == "GET":
        return render(request,"lagrange.html",{'user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        if i.has_key('ok'):  # 点击上传
            try:
                csv_file = request.FILES["csv"].read()
                fobj = StringIO.StringIO(csv_file) # 获取上传的文件 
                csv_result =list(csv.reader(fobj))
                csv_result = csv_result[1:]   # 除去表头
                k = int(request.POST['value_k'])
                lag_list_x = []
                lag_list_y = []

                for i in range(len(csv_result)):
                    if csv_result[i][1] != '':
                        csv_result[i] = map(float,csv_result[i])
                    else:
                        csv_result[i][0] = float(csv_result[i][0])
                        csv_result[i][1] = ''
                for i in csv_result:
                    lag_list_x.append(i[0])
                    lag_list_y.append(i[1])

                result = data_isnull(lag_list_x,lag_list_y,k)

                data = [{'name':'原始数据','type':'scatter','data':csv_result,'symbolSize':8},
                        {'name':'插值结果','type':'scatter','data':result,'symbolSize':8}]
                data = json.dumps(data,ensure_ascii=False)
                return render(request,'lagrange.html',{'result':result,
                                                        'k':k,
                                                        'lag_list_x':lag_list_x,
                                                        'lag_list_y':lag_list_y,
                                                        'data':data,
                                                        'csv':csv_result,
                                                        'user':request.session['username']},
                                                        context_instance=RequestContext(request))
            except:
                return render(request,'404.html')

def pca(request):
    if request.method == "GET":
        return render(request,"pca.html",{'user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        if i.has_key('ok'):  # 点击上传
            try:
                csv_file = request.FILES["csv"].read()
                fobj = StringIO.StringIO(csv_file) # 获取上传的文件 
                csv_result =list(csv.reader(fobj))
                n1 = int(request.POST['n1'])
                n2 = int(request.POST['n2'])

                Xname = json.dumps(csv_result[0][0],ensure_ascii=False)
                Yname = json.dumps(csv_result[0][1],ensure_ascii=False)
                shuxing = csv_result[0]
                csv_result = csv_result[1:]

                for i in range(len(csv_result)):
                    csv_result[i] = map(float,csv_result[i])
                
                result = pca_model(csv_result,n2)
                res = []
                for i in result:
                    res.append([float(i),0])

                data1 = [{'name':'原始数据','type':'scatter','data':csv_result,'symbolSize':8}]
                data1 = json.dumps(data1,ensure_ascii=False)
                data2 = [{'name':'PCA分析结果','type':'scatter','data':res,'symbolSize':8}]
                data2 = json.dumps(data2,ensure_ascii=False) 

                return render(request,'pca.html',{'result':res,
                                                    'data1':data1,
                                                    'data2':data2,
                                                    'Xname':Xname,
                                                    'Yname':Yname,
                                                    'n1':n1,
                                                    'n2':n2,
                                                    'user':request.session['username'],
                                                        },
                                                        context_instance=RequestContext(request))
            except:
                return render(request,'404.html')


def decision_tree(request):               
    if request.method == "GET":
        return render(request,"decision_tree.html",{'user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        if i.has_key('ok'):  # 点击上传
            try:
                csv_file = request.FILES["csv"].read()
                fobj = StringIO.StringIO(csv_file) # 获取上传的文件 
                csv_result =list(csv.reader(fobj))
                shuxing = csv_result[0][:-1] 
                csv_result = csv_result[1:]
            
                for i in range(len(csv_result)):
                    for j in range(len(csv_result[0]) - 1):
                        csv_result[i][j] = float(csv_result[i][j])
            
                test_set = (request.POST['testset_input']).split(",")
                test_set = map(float,test_set)
                test_set2 = {}  # 最后test_set2[0]为测试集
                for i in range(len(shuxing)):
                    test_set2[shuxing[i]] = float(test_set[i])
            

                tree = treeGrowth(csv_result,shuxing)  # 构造树
                result = ID3_predict(tree,test_set2)   # 测试集的分类结果        
             
                return render(request,'decision_tree.html',{'result':result,
                                                            'tree':tree,
                                                            'test_set':test_set,
                                                            'user':request.session['username'],
                                                            },
                                                            context_instance=RequestContext(request))
            except:
                return render(request,'404.html')


def k_means(request):
    if request.method == "GET":
        return render(request,"k-means.html",{'user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        if i.has_key('ok'):  # 点击上传
            try:
                k = int(request.POST['value_k'])
                csv_file = request.FILES["csv"].read()
                fobj = StringIO.StringIO(csv_file) # 获取上传的文件 
                csv_result = list(csv.reader(fobj))
            
                Xname = json.dumps(csv_result[0][0],ensure_ascii=False)
                Yname = json.dumps(csv_result[0][1],ensure_ascii=False)
                shuxing = csv_result[0]
                csv_result = csv_result[1:]

                for i in range(len(csv_result)):
                    csv_result[i] = map(float,csv_result[i])
            
                b = random_k(csv_result,k)
                record=kmeans_model(csv_result,k,b)        #整个过程 记录在record 中
                a=len(record)-1

                result=[]         # 聚类结果的2维列表
                for i in range(len(record[a])):
                    result.append([ ])
                    for j in range(len(record[a][i])):
                        result[i].append(csv_result[record[a][i][j]])

                labels = []   # 传给echarts
                for i in range(k):
                    flag = 'Group '+str(i+1)
                    labels.append(flag)


                if len(csv_result[0]) == 2:   # 散点图
                    data=[]    # 传给echarts
                    for i in range(len(labels)):
                        data.append({'name':labels[i],'type':'scatter','data':result[i],'symbolSize':8})
                    data = json.dumps(data,ensure_ascii=False)

                    return render(request,'k-means.html',{'result':result,
                                                        'data':data,
                                                        'labels':labels,
                                                        'k':k,
                                                        'Xname':Xname,
                                                        'Yname':Yname,
                                                        'length':len(csv_result[0]),
                                                        'user':request.session['username'],
                                                        },
                                                            context_instance=RequestContext(request))


                elif len(csv_result[0]) > 2:   # 雷达图
                    data = []
                    per_label = []   
                    for i in range(len(result)):
                        for j in result[i]:
                            flag = 'Group '+str(i+1)
                            per_label.append(flag)

                    for i in range(len(csv_result)):
                        data.append({'name':per_label[i],'value':csv_result[i]})
                    data = json.dumps(data,ensure_ascii=False)

                    numb = np.array(csv_result)   # 文件中所有数字
                    numb = numb.transpose()     # 矩阵转置
                    indicator = []  # 传给echarts
                    for i in range(len(shuxing)):
                        indicator.append({'text':shuxing[i],'max':max(numb[i])})

                    return render(request,'k-means.html',{'result':result,
                                                        'data':data,
                                                        'labels':labels,
                                                        'k':k,
                                                        'indicator':indicator,
                                                        'length':len(csv_result[0]),
                                                        'user':request.session['username'],
                                                        },
                                                            context_instance=RequestContext(request))
            except:
                return render(request,'404.html')



def RA_line(request):    
    if request.method == "GET":
        return render(request,"RA_line.html",{'user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        if i.has_key('ok'):  # 点击上传
            try:
                csv_file = request.FILES["csv"].read()
                fobj = StringIO.StringIO(csv_file) # 获取上传的文件 
                csv_result =list(csv.reader(fobj))
                x = float(request.POST['x'])

                Xname = json.dumps(csv_result[0][0],ensure_ascii=False)
                Yname = json.dumps(csv_result[0][1],ensure_ascii=False)

                csv_result = csv_result[1:]   # 除去表头
                for i in range(len(csv_result)):
                    csv_result[i] = map(float,csv_result[i])

                numb = np.array(csv_result)
                numb = numb.transpose()
                max_x = int(max(numb[0]))+3  # 画折线图要用的范围
                min_x = int(min(numb[0]))-3

                aver_x = average_(csv_result,0)           # x 均值
                aver_y = average_(csv_result,1)           # y 均值
                xx = evaluate_xx(csv_result,aver_x)           
                yy = evaluate_yy(csv_result,aver_y)           # TSS 总离差平方和
                xy = evaluate_xy(csv_result,aver_x,aver_y)    # 

                a  =xy/xx                         #回归方程 斜率
                b = aver_y-a*aver_x               #回归方程 截距
                sse = yy-a*xy                     # 结果分析   残差平方和
                r = xy/(xx*yy)**0.5               # 结果分析   相关系数
                s = 1-(sse/yy)                    # 结果分析   拟合系数
                result = a*x+b                    # 预测的一个值
            
                list_result = []
                data_x = []
                for i in range(min_x,max_x):
                    data_x.append(i)
                    list_result.append(a*i+b)
            

                data = [{'name':'原始数据','type':'scatter','data':csv_result,'symbolSize':8}]
                data = json.dumps(data,ensure_ascii=False)
                series = [{'name':'回归分析结果','type':'line','data':list_result}]
                series = json.dumps(series,ensure_ascii=False)


                return render(request,'RA_line.html',{'result':result,
                                                        'data':data,
                                                        'data_x':data_x,
                                                        'series':series,
                                                        'x':x,
                                                        'Xname':Xname,
                                                        'Yname':Yname,
                                                        'r':r, #相关系数
                                                        's':s, #拟合系数
                                                        'a':a, 
                                                        'b':b,
                                                        'b2':abs(b),
                                                        'user':request.session['username'],
                                                        },
                                                        context_instance=RequestContext(request))

            except:
                return render(request,'404.html')

def xtjl(request):    
    if request.method == "GET":
        return render(request,"xtjl.html",{'user':request.session['username']})
    if request.method == 'POST':
        i = request.POST
        if i.has_key('ok'):  
            try:
                csv_file = request.FILES["csv"].read()
                fobj = StringIO.StringIO(csv_file)  
                csv_result =list(csv.reader(fobj))
                data = []
                for i in csv_result[1:]:
                    data.append(map(float,i))
                record=main(data)
                for i in range(len(record)):
                    record[i] = record[i][1:]
                return render(request,'xtjl.html',{'record':record,
                                                    'user':request.session['username'],
                                                        },
                                                        context_instance=RequestContext(request))
            except:
                return render(request,'404.html')


            